/* main.c */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <signal.h>

#include "protocol.h"
#include "process.h" 

#define MAX_CLIENTS 100
#define BUFFER_SIZE 512


#define MAX_CLIENT 256

int fd2id_flag[MAX_CLIENT];
int id2fd_flag[MAX_CLIENT];
int fd2id_array[MAX_CLIENT];
int id2fd_array[MAX_CLIENT];

int fd2id(int);
int id2fd(int);

int send_msg(int fd, const char * msg);

void sigint_handler(int);

int main()
{
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;
    int result;
    
    char buffer[BUFFER_SIZE];
    fd_set readfds, testfds;
    
    protocol_t in_msg;
    protocol_t out_msg;
    tbs_init();
    
    if(signal(SIGINT, sigint_handler) == SIG_ERR ){
    	perror("Cannot register singnal handler");
    	tbs_end();
    }

    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(9999);
    server_len = sizeof(server_address);

    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

    listen(server_sockfd, 5);

    FD_ZERO(&readfds);
    FD_SET(server_sockfd, &readfds);


    while(1) {
        int fd;
        int nread;

        testfds = readfds;

        printf("TBS Server Waiting...\n");
        result = select(FD_SETSIZE, &testfds, (fd_set *)0, 
            (fd_set *)0, (struct timeval *) 0);
        if(result < 1) {
            fputs("Error occured in select",stderr);
            exit(1);
        }

        for(fd = 0; fd < FD_SETSIZE; fd++) {
            if(FD_ISSET(fd,&testfds)) {
                if(fd == server_sockfd) {
                    client_len = sizeof(client_address);
                    client_sockfd = accept(server_sockfd, 
                        (struct sockaddr *)&client_address, &client_len);
                    FD_SET(client_sockfd, &readfds);
                    printf("Adding client on fd %d\n", client_sockfd);
                }else {
                    ioctl(fd, FIONREAD, &nread);
                    if(nread == 0) {
                        close(fd);
                        FD_CLR(fd, &readfds);
                        printf("Removing client on fd %d\n", fd);
                    }else {
                        read(fd, buffer, nread);
                        buffer[nread] = '\0';
                        printf("Get msg [%s]\n", buffer); 
	
			if(parse_msg(&in_msg, buffer) != 0){
				fprintf(stderr,"Cannot parse messege!");
				break;
			}
			if(process_action(fd, &in_msg, &out_msg, send_msg)!=0){
				break;
			}
			//send msg
			format_msg(&out_msg, buffer);
			printf("Formatted String[%s]\n", buffer);
			printf("id = %d\n", out_msg.usr_id);
			write(fd, buffer,strlen(buffer));
			break;
                    }
                }
            }
        }
    }
}


int send_msg(int fd, const char * msg){
	printf("Formatted String[%s]\n", msg);
	write(fd, msg,strlen(msg));
	return 0;
}

int fd2id(int i){
	if(fd2id_flag[i] != 1){
		return -1;
	}else {
		return fd2id_array[i];
	}
}

int id2fd(int i){
	if(id2fd_flag[i] != 1){
		return -1;
	}else {
		return id2fd_array[i];
	}
}

void sigint_handler(int sig) {
	if(sig == SIGINT){
		tbs_end();
		printf("shutting down server ... ");
		exit(0);
	}
	return;
}

